package corp.edu.amadeus.core.dao.impl.callback;

import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import org.hibernate.Criteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.springframework.orm.hibernate3.HibernateCallback;
import corp.edu.amadeus.commons.Constants;

public class FindByCriteriaCallback implements HibernateCallback {

    private final Class target;
    private final Collection criterion;
    private final Collection projections;
    private boolean isOrdered = false;
    private String order_type = "";
    private String order_property = "";
    private int max_results = 0;



    public FindByCriteriaCallback(final Class target,
	    final Collection criterion, final Collection projections,
	    final String orderProperty ,
	    final String orderType, final int maxResults) {
        super();
        this.target = target;
        this.criterion = criterion;
        this.isOrdered = true;
        this.order_property = orderProperty;
        this.order_type = orderType;
        this.max_results = maxResults;
        this.projections = projections;
    }

    public FindByCriteriaCallback(final Class target,
	    final Collection criterion, final Collection projections
	    , final int maxResults) {
        super();
        this.target = target;
        this.criterion = criterion;
        this.max_results = maxResults;
        this.projections = projections;
    }

    public Object doInHibernate(Session session)
    	throws HibernateException,
        SQLException {
        Criteria criteria = this.aggregateCriterion(this.target,
        	this.criterion, this.projections, session);
        return criteria.list();
    }

    private Criteria aggregateCriterion(Class target, Collection criterion,
        Collection projections, Session ses) throws HibernateException {
        Criteria criteria = ses.createCriteria(target);
        Iterator it = criterion.iterator();
        Criterion criterion_H;
        while (it.hasNext()) {
            criterion_H = (Criterion)it.next();
            criteria.add(criterion_H);
        }
        if(this.isOrdered) {
            if(Constants.ASC_ORDER.equals(this.order_type)) {
        	criteria.addOrder(Order.asc(this.order_property));
            }else {
        	criteria.addOrder(Order.desc(this.order_property));
            }

        }
        //System.out.println("Numero de projections: " + projections.size());
        if(projections.size()>0) {
            ProjectionList projList = Projections.projectionList();
            it = projections.iterator();
            while (it.hasNext()) {
                projList.add((Projection)it.next());
            }
            criteria.setProjection(projList);
        }
        if(this.max_results > 0) {
            criteria.setMaxResults(this.max_results);
        }

        return criteria;
    }

}